home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
lang
/
fpcsrc.lha
/
fpc
/
compiler
/
cgai386.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-09-24
|
51KB
|
1,291 lines
{
$Id: cgai386.pas,v 1.4.2.1 1998/04/09 23:29:23 peter Exp $
Copyright (c) 1993-98 by Florian Klaempfl
This unit generates i386 (or better) assembler from the parse tree
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************}
unit cgai386;
interface
uses
objects,cobjects,systems,globals,tree,symtable,types,strings,
pass_1,hcodegen,aasm,i386,tgeni386,files,verbose
{$ifdef GDB}
,gdb
{$endif GDB}
;
procedure emitl(op : tasmop;var l : plabel);
procedure emit_reg_reg(i : tasmop;s : topsize;reg1,reg2 : tregister);
procedure emitcall(const routine:string;add_to_externals : boolean);
procedure emitloadord2reg(location:Tlocation;orddef:Porddef;
destreg:Tregister;delloc:boolean);
{ produces jumps to true respectively false labels using boolean expressions }
procedure maketojumpbool(p : ptree);
procedure emitoverflowcheck(p:ptree);
procedure push_int(l : longint);
function maybe_push(needed : byte;p : ptree) : boolean;
procedure restore(p : ptree);
procedure emit_push_mem(const ref : treference);
procedure emitpushreferenceaddr(const ref : treference);
procedure swaptree(p:Ptree);
procedure copystring(const dref,sref : treference;len : byte);
procedure loadstring(p:ptree);
procedure concatcopy(source,dest : treference;size : longint;delsource : boolean);
{ see implementation }
procedure maybe_loadesi;
procedure floatload(t : tfloattype;const ref : treference);
procedure floatstore(t : tfloattype;const ref : treference);
procedure floatloadops(t : tfloattype;var op : tasmop;var s : topsize);
procedure floatstoreops(t : tfloattype;var op : tasmop;var s : topsize);
procedure firstcomplex(p : ptree);
procedure secondfuncret(var p : ptree);
{ initialize respectively terminates the code generator }
{ for a new module or procedure }
procedure codegen_doneprocedure;
procedure codegen_donemodule;
procedure codegen_newmodule;
procedure codegen_newprocedure;
{ generate entry code for a procedure.}
procedure genentrycode(const proc_names:Tstringcontainer;make_global:boolean;
stackframe:longint;
var parasize:longint;var nostackframe:boolean);
{ generate the exit code for a procedure. }
procedure genexitcode(parasize:longint;nostackframe:boolean);
implementation
{
procedure genconstadd(size : topsize;l : longint;const str : string);
begin
if l=0 then
else if l=1 then
exprasmlist^.concat(new(pai386,op_A_INC,size,str)
else if l=-1 then
exprasmlist^.concat(new(pai386,op_A_INC,size,str)
else
exprasmlist^.concat(new(pai386,op_ADD,size,'$'+tostr(l)+','+str);
end;
}
procedure copystring(const dref,sref : treference;len : byte);
var
pushed : tpushed;
begin
emitpushreferenceaddr(dref);
emitpushreferenceaddr(sref);
push_int(len);
emitcall('STRCOPY',true);
maybe_loadesi;
end;
procedure loadstring(p:ptree);
begin
case p^.right^.resulttype^.deftype of
stringdef : begin
if (p^.right^.treetype=stringconstn) and
(p^.right^.values^='') then
exprasmlist^.concat(new(pai386,op_const_ref(
A_MOV,S_B,0,newreference(p^.left^.location.reference))))
else
copystring(p^.left^.location.reference,p^.right^.location.reference,
min(pstringdef(p^.right^.resulttype)^.len,pstringdef(p^.left^.resulttype)^.len));
end;
orddef : begin
if p^.right^.treetype=ordconstn then
exprasmlist^.concat(new(pai386,op_const_ref(
A_MOV,S_W,p^.right^.value*256+1,newreference(p^.left^.location.reference))))
else
begin
{ not so elegant (goes better with extra register }
if (p^.right^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
begin
exprasmlist^.concat(new(pai386,op_reg_reg(
A_MOV,S_L,reg8toreg32(p^.right^.location.register),R_EDI)));
ungetregister32(reg8toreg32(p^.right^.location.register));
end
else
begin
exprasmlist^.concat(new(pai386,op_ref_reg(
A_MOV,S_L,newreference(p^.right^.location.reference),R_EDI)));
del_reference(p^.right^.location.reference);
end;
exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,8,R_EDI)));
exprasmlist^.concat(new(pai386,op_const_reg(A_OR,S_L,1,R_EDI)));
exprasmlist^.concat(new(pai386,op_reg_ref(
A_MOV,S_W,R_DI,newreference(p^.left^.location.reference))));
end;
end;
else
Message(sym_e_type_mismatch);
end;
end;
procedure restore(p : ptree);
var
hregister : tregister;
begin
hregister:=getregister32;
exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,hregister)));
if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
p^.location.register:=hregister
else
begin
reset_reference(p^.location.reference);
p^.location.reference.index:=hregister;
set_location(p^.left^.location,p^.location);
end;
end;
function maybe_push(needed : byte;p : ptree) : boolean;
var
pushed : boolean;
{hregister : tregister; }
begin
if needed>usablereg32 then
begin
if (p^.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
begin
pushed:=true;
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,p^.location.register)));
ungetregister32(p^.location.register);
end
else if (p^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
((p^.location.reference.base<>R_NO) or
(p^.location.reference.index<>R_NO)
) then
begin
del_reference(p^.location.reference);
exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(p^.location.reference),
R_EDI)));
exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EDI)));
pushed:=true;
end
else pushed:=false;
end
else pushed:=false;
maybe_push:=pushed;
end;
procedure emitl(op : tasmop;var l : plabel);
begin
if op=A_LABEL then
exprasmlist^.concat(new(pai_label,init(l)))
else
exprasmlist^.concat(new(pai_labeled,init(op,l)))
end;
procedure em